home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / dev / lang / PPCsmalltalk.lha / PPCSmallTalk / sources / process.c < prev    next >
C/C++ Source or Header  |  1986-10-19  |  6KB  |  255 lines

  1. /*
  2.     Little Smalltalk
  3.  
  4.         process manager
  5.         dennis a. vadner and michael t. benhase, 11/84
  6.         modified by timothy a. budd 4/85
  7. */
  8. /*
  9.     The source code for the Little Smalltalk System may be freely
  10.     copied provided that the source of all files is acknowledged
  11.     and that this condition is copied with each file.
  12.  
  13.     The Little Smalltalk System is distributed without responsibility
  14.     for the performance of the program and without any guarantee of
  15.     maintenance.
  16.  
  17.     All questions concerning Little Smalltalk should be addressed to:
  18.  
  19.         Professor Tim Budd
  20.         Department of Computer Science
  21.         The University of Arizona
  22.         Tucson, Arizona
  23.         85721
  24.         USA
  25. */
  26.  
  27. # include "object.h"
  28.  
  29. # include <stdio.h>
  30.  
  31. #undef SIGS
  32. # ifdef SIGS
  33. # include <signal.h>
  34. # endif
  35.  
  36. # ifdef SETJUMP
  37. # include <setjmp.h>
  38. # endif
  39.  
  40. # include "drive.h"
  41. # include "interp.h"
  42. # include "process.h"
  43.  
  44. extern int  test_driver();    /* routine to test for user keystrokes*/
  45.  
  46. static process  *currentProcess;    /* current process */
  47. static process  *fr_process = 0;    /* process memory free list */
  48.  
  49. int  atomcnt = 0;            /* atomic action flag */
  50. process  *runningProcess;        /* currently running process,
  51.                        may be different from
  52.                        currentProcess during process
  53.                        termination */
  54.  
  55. # define PROCINITMAX 6
  56. static process prcinit[PROCINITMAX];    /* initial process free list */
  57.  
  58.  
  59. /* init_process - initialize the process module */
  60. init_process ()
  61. {    process *p;
  62.     int i;
  63.  
  64.     /* first make the initial process free list */
  65.     for (p = prcinit, i = 0; i < PROCINITMAX; i++, p++) {
  66.         p->next = fr_process;
  67.         fr_process = p;
  68.         }
  69.  
  70.     /* make the process associated with the driver */
  71.     currentProcess = cr_process(o_drive);
  72.     assign(currentProcess->next, currentProcess);
  73.     assign(currentProcess->prev, currentProcess);
  74.     currentProcess->p_state = ACTIVE;
  75. }
  76.  
  77. /* cr_process - create a new process with the given interpreter */
  78. process  *cr_process (anInterpreter)
  79. interpreter  *anInterpreter;
  80. {    process  *new;
  81.  
  82.     if (fr_process) {
  83.         new = (process *) fr_process;
  84.         fr_process = fr_process->next;
  85.         }
  86.     else
  87.         new = structalloc(process);
  88.  
  89.     new->p_ref_count = 0;
  90.     new->p_size = PROCSIZE;
  91.  
  92.     sassign(new->interp, anInterpreter);
  93.     new->p_state = SUSPENDED;
  94.     sassign(new->next, (process *) o_nil);
  95.     sassign(new->prev, (process *) o_nil);
  96.  
  97.     return(new);
  98. }
  99.  
  100.  
  101. /* free_process - return an unused process to free list */
  102. free_process (aProcess)
  103. process  *aProcess;
  104. {
  105.     obj_dec((object *) aProcess->interp);
  106.     obj_dec((object *) aProcess->next);
  107.     obj_dec((object *) aProcess->prev);
  108.     aProcess->p_state = TERMINATED;
  109.     aProcess->next = fr_process;
  110.     fr_process = aProcess;
  111. }
  112.  
  113. /* flush_processes - flush out any remaining process from queue */
  114. flush_processes ()
  115. {
  116.     while (currentProcess != currentProcess->next)
  117.        remove_process(currentProcess);
  118.  
  119.     /* prev link and next link should point to the same place now.
  120.        In order to avoid having memory recovered while we are
  121.        manipulating pointers, we increment reference count, then change
  122.        pointers, then decrement reference counts */
  123.  
  124.     obj_inc((object *) currentProcess);
  125.     safeassign(currentProcess->prev, (process *) o_nil);
  126.     safeassign(currentProcess->next, (process *) o_nil);
  127.     obj_dec((object *) currentProcess);
  128. }
  129.  
  130.  
  131. /* link_to_process - change the interpreter for the current process */
  132. link_to_process (anInterpreter)
  133. interpreter  *anInterpreter;
  134. {    object *temp;
  135.  
  136.     safeassign(runningProcess->interp, anInterpreter);
  137. }
  138.  
  139.  
  140. /* remove_process - remove a process from process queue */
  141. static remove_process (aProcess)
  142. process  *aProcess;
  143. {
  144.     if (aProcess == aProcess->next)
  145.         cant_happen(15);        /* removing last active process */
  146.  
  147.     /* currentProcess must always point to a process that is on the
  148.        process queue, make sure this remains true */
  149.  
  150.     if (aProcess == currentProcess)
  151.         currentProcess = currentProcess->prev;
  152.  
  153.     /* In order to avoid having memory recovered while we are changing
  154.     pointers, we increment the reference counts on both processes,
  155.     change pointers, then decrement reference counts */
  156.  
  157.     obj_inc((object *) currentProcess); obj_inc((object *) aProcess);
  158.     safeassign(aProcess->next->prev, aProcess->prev);
  159.     safeassign(aProcess->prev->next, aProcess->next);
  160.     obj_dec((object *) currentProcess); obj_dec((object *) aProcess);
  161. }
  162.  
  163.  
  164. /* schedule_process - add a new process to the process queue */
  165. static schedule_process (aProcess)
  166. process  *aProcess;
  167. {
  168.     safeassign(aProcess->next, currentProcess);
  169.     safeassign(aProcess->prev, currentProcess->prev);
  170.     safeassign(aProcess->prev->next, aProcess);
  171.     safeassign(currentProcess->prev, aProcess);
  172. }
  173.  
  174. /* set_state - set the state on a process, which may involve inserting or
  175. removing it from the process queue */
  176. int  set_state (aProcess, state)
  177. process  *aProcess;
  178. int  state;
  179. {
  180.     switch (state) {
  181.         case BLOCKED:
  182.         case SUSPENDED:
  183.         case TERMINATED:    if (aProcess->p_state == ACTIVE)
  184.                     remove_process(aProcess);
  185.                 aProcess->p_state |= state;
  186.                 break;
  187.  
  188.         case READY:
  189.         case UNBLOCKED:    if ((aProcess->p_state ^ state) == ~ACTIVE)
  190.                     schedule_process(aProcess);
  191.                 aProcess->p_state &= state;
  192.                 break;
  193.  
  194.         case CUR_STATE:    break;
  195.         default:        cant_happen(17);
  196.         }
  197.     return(aProcess->p_state);
  198. }
  199.  
  200. # ifdef SETJUMP
  201. static jmp_buf intenv;
  202. # endif
  203.  
  204. /* brkfun - what to do on a break key */
  205. brkfun()
  206. {    static int warn = 1;
  207.  
  208. # ifndef SETJUMP
  209.     exit(1);
  210. # endif
  211.     if (warn) {
  212.         fprintf(stderr,"warning: recovery from interrupt may cause\n");
  213.         fprintf(stderr,"reference counts to be incorrect, and\n");
  214.         fprintf(stderr,"some memory to be inaccessible\n");
  215.         warn = 0;
  216.         }
  217. # ifdef SETJUMP
  218.     longjmp(intenv, 1);
  219. # endif
  220. }
  221.  
  222. /* start_execution - main execution loop */
  223. start_execution ()
  224. {    interpreter  *presentInterpreter;
  225.  
  226.     atomcnt = 0;
  227.  
  228. # ifdef SIGS
  229.     /* trap user interrupt signals and recover */
  230.     signal(SIGINT, brkfun);
  231. # endif
  232.  
  233. # ifdef SETJUMP
  234.     if (setjmp(intenv)) {
  235.         atomcnt = 0;
  236.         link_to_process(o_drive);
  237.         }
  238. # endif
  239.  
  240.     while (1) {
  241.         /* unless it is an atomic action get the next process */
  242.         if (! atomcnt)
  243.         runningProcess = currentProcess = currentProcess->next;
  244.  
  245.         if (! is_driver(runningProcess->interp)) {
  246.         sassign(presentInterpreter, runningProcess->interp);
  247.         resume(presentInterpreter);
  248.         obj_dec((object *) presentInterpreter);
  249.         }
  250.         else if (! test_driver((currentProcess == currentProcess->next) ||
  251.                    (atomcnt > 0)))
  252.         break;
  253.         }
  254. }
  255.